package com.h3c.ptability.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.h3c.ptability.bo.EmailAttachmentBO;
import com.h3c.ptability.bo.SendEmailBO;
import com.h3c.ptability.config.properties.PtAbilityEmailProperties;
import com.h3c.ptability.config.properties.SendEmailProperties;
import com.h3c.ptability.support.MailAuthenticator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.File;
import java.util.*;

/**
 * @author chenyifan
 * @date 2022/6/14 13:18
 */
@Slf4j
@Component
public class EmailUtil {


    private static PtAbilityEmailProperties ptAbilityEmailProperties;

    @Resource(name = "baseSendEmail")
    public void setEmailProperties(PtAbilityEmailProperties emailProperties) {
        EmailUtil.ptAbilityEmailProperties = emailProperties;
    }

    /**
     * 发送邮件
     *
     * @param emailBO 邮件信息
     * @return
     */
    public static HashMap<String, String> sendEmail(SendEmailBO emailBO) {
        HashMap<String, String> map = new HashMap<>(2);
        map.put("state", "success");
        String message = "邮件发送成功！";
        Session session;
        Properties props = System.getProperties();
        SendEmailProperties emailProperties;
        if ("nem-manager".equals(emailBO.getAppId())) {
            emailProperties = ptAbilityEmailProperties.getNemManager();
        } else if ("dept-manager".equals(emailBO.getAppId())) {
            emailProperties = ptAbilityEmailProperties.getDeptManager();
        } else if ("hr-leaderexam".equals(emailBO.getAppId()) || "leaderexam-test".equals(emailBO.getAppId())) {
            emailProperties = ptAbilityEmailProperties.getHrMrs();
        } else if ("hr-sign".equals(emailBO.getAppId()) ||
                "hr-sign-test".equals(emailBO.getAppId()) ||
                "e-sign-platform".equals(emailBO.getAppId())){
            emailProperties = ptAbilityEmailProperties.getHrSign();
        } else if ("hrmp-manage".equals(emailBO.getAppId())) {
            emailProperties = ptAbilityEmailProperties.getHrmpManage();
        } else if ("LBM".equals(emailBO.getAppId())) {
            emailProperties = ptAbilityEmailProperties.getH3cuLbm();
        } else if ("h3cu-lbm".equals(emailBO.getAppId())) {
            emailProperties = ptAbilityEmailProperties.getH3cuLbm();
        } else if ("hrcp-sse".equals(emailBO.getAppId())) {
            emailProperties = ptAbilityEmailProperties.getHrSse();
        } else if ("hrdataboard".equals(emailBO.getAppId())) {
            emailProperties = ptAbilityEmailProperties.getHrBroad();
        }
        else {
            throw new AppBusinessException("不存在应用对应的邮箱配置");
        }
        //如果是测试环境，邮件发送到配置的指定收件人，邮件正文中写入收件人和抄送人
        if ("test".equals(emailProperties.getEnv())) {
            String addContent = "<p><br></p><p>收件人：{收件人}</p><p><br></p><p>抄送人：{抄送人}</p>";
            if (!StringUtils.isEmpty(emailBO.getTargetAccount())) {
                addContent = addContent.replace("{收件人}", emailBO.getTargetAccount());
            } else {
                if (!StringUtils.isEmpty(emailBO.getTargetId())) {
                    addContent = addContent.replace("{收件人}", emailBO.getTargetId());
                }
            }
            if (!StringUtils.isEmpty(emailBO.getCopyToAccount())) {
                addContent = addContent.replace("{抄送人}", emailBO.getCopyToAccount());
            } else {
                if (!StringUtils.isEmpty(emailBO.getCopyToId())) {
                    addContent = addContent.replace("{抄送人}", emailBO.getCopyToId());
                }
            }
//            addContent = addContent.replace("{收件人}",emailBO.getToEmail()).replace("{抄送人}",emailBO.getCcEmail());
            emailBO.setContent(emailBO.getContent() + addContent);
            emailBO.setToEmail(emailProperties.getTestEmail());
        }
        if (!emailProperties.getSendFlag()) {
            return map;
        }
        props.put("mail.smtp.host", emailProperties.getSmtpServer());

        if (emailProperties.getIfAuth()) {
            props.put("mail.smtp.auth", "true");
            MailAuthenticator smtpAuth = new MailAuthenticator(emailProperties.getSmtpUserName(), emailProperties.getSmtpPassword());
            session = Session.getDefaultInstance(props, smtpAuth);
        } else {
            props.put("mail.smtp.auth", "false");
            session = Session.getDefaultInstance(props, null);
        }
        session.setDebug(true);
        Transport trans;
        try {
            Message msg = new MimeMessage(session);
            try {
                Address fromAddress = new InternetAddress(emailProperties.getSmtpFrom(), emailProperties.getSmtpDisplayName());
                msg.setFrom(fromAddress);
            } catch (java.io.UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            //收件人
            if (StringUtils.isNotBlank(emailBO.getToEmail())) {
                String[] ccEmail = emailBO.getToEmail().split(",");
                for (String email : ccEmail) {
                    msg.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
                }
            }
            if (StringUtils.isNotBlank(emailBO.getCcEmail())) {
                String[] ccEmail = emailBO.getCcEmail().split(",");
                for (String email : ccEmail) {
                    msg.addRecipient(Message.RecipientType.CC, new InternetAddress(email));
                }
            }
            if (StringUtils.isNotBlank(emailBO.getBccEmail())) {
                String[] bccEmail = emailBO.getBccEmail().split(",");
                for (String email : bccEmail) {
                    msg.addRecipient(Message.RecipientType.BCC, new InternetAddress(email));
                }
            }

            msg.setSubject(emailBO.getSubject());
            Multipart mp = new MimeMultipart();
            MimeBodyPart mbp = new MimeBodyPart();
            mbp.setContent(emailBO.getContent(), "text/html;charset=UTF-8");
            mp.addBodyPart(mbp);
            ArrayList<File> needDelFile = new ArrayList<>();
            // 添加附件
            if (Objects.nonNull(emailBO.getAttachmentBOList()) && emailBO.getAttachmentBOList().size() > 0) {
                for (EmailAttachmentBO attachmentBO : emailBO.getAttachmentBOList()) {
                    BodyPart messageBodyPart = new MimeBodyPart();
                    try {
                        File temp = FileUtil.writeBytes(Base64.decode(attachmentBO.getAttachment()), EmailUtil.class.getResource("/").toString() + "/temp/email/" + IdUtil.randomUUID() + ".docx");
                        DataSource source = new FileDataSource(temp);
                        // 添加附件的内容
                        messageBodyPart.setDataHandler(new DataHandler(source));
                        // 添加附件的标题
                        // 这里很重要，通过下面的Base64编码的转换可以保证你的中文附件标题名在发送时不会变成乱码
                        messageBodyPart.setFileName(MimeUtility.encodeText(attachmentBO.getAttachmentName()));
                        mp.addBodyPart(messageBodyPart);
                        needDelFile.add(temp);
                    } catch (Exception e) {
                        log.error("添加邮件附件失败,原因:{}", e.getMessage());
                        e.printStackTrace();
                    }
                }
            }
            // Multipart加入到信件
            msg.setContent(mp);
            // 设置信件头的发送日期
            msg.setSentDate(new Date());
            // 发送信件
            msg.saveChanges();
            trans = session.getTransport("smtp");
            trans.connect(emailProperties.getSmtpServer(), emailProperties.getSmtpUserName(), emailProperties.getSmtpPassword());
            trans.sendMessage(msg, msg.getAllRecipients());
            trans.close();
            needDelFile.forEach(s -> FileUtil.del(s));
        } catch (AuthenticationFailedException e) {
            log.error(message, e);
            map.put("state", "failed");
            message = "邮件发送失败！错误原因：\n" + "身份验证错误!";
        } catch (MessagingException e) {
            log.error(message, e);
            map.put("state", "failed");
            message = "邮件发送失败！错误原因：\n" + e.getMessage();
        }
        map.put("message", message);
        return map;
    }


    /**
     * 转义正则特殊字符 （$()*+.[]?\^{}
     * \\需要第一个替换，否则replace方法替换时会有逻辑bug
     *
     * @param str
     * @return
     */
    public static String makeQueryStringAllRegExp(String str) {
        if (org.springframework.util.StringUtils.isEmpty(str)) {
            return str;
        }
        return str.replace("\\", "\\\\").replace("*", "\\*")
                .replace("+", "\\+").replace("|", "\\|")
                .replace("{", "\\{").replace("}", "\\}")
                .replace("(", "\\(").replace(")", "\\)")
                .replace("^", "\\^").replace("$", "\\$")
                .replace("[", "\\[").replace("]", "\\]")
                .replace("?", "\\?").replace(",", "\\,")
                .replace(".", "\\.").replace("&", "\\&");
    }
}
